home *** CD-ROM | disk | FTP | other *** search
- /*
- * Blob Manager Demonstration: Tic-Tac-Toe
- *
- * 25 July 1986 Paul DuBois
- *
- * 28 Dec 93
- * - Convert from picture blobs to procedure blobs
- */
-
- # include "TransSkel.h"
-
- # include "BlobMgr.h"
- # include "BlobDemo.h"
-
-
- # define barWidth 3 /* board line size */
- # define bSqSize 30 /* board square size */
- # define pSqSize 28 /* playing piece square size */
- # define yOffMesg 4
- # define yOffPiece 24 /* offset of top of pieces */
- # define xOffBoard 25
- # define yOffBoard 59
- # define xMid 73 /* xOffBoard + 1.5(bSqSize) + barWidth */
- # define yOffBut 165
-
-
- static WindowPtr wind;
- static BlobSetHandle tttReceptors; /* receptor blobs (board) */
- static BlobSetHandle tttDonors; /* donor blobs (pieces) */
- static BlobHandle xBlob; /* handles to each piece */
- static BlobHandle oBlob;
-
- static Boolean haveWin;
- static Boolean wait = false;
- static ControlHandle restartCtl;
- static short moves;
- static short firstPlayer = 0;
- static Str255 statusStr;
-
-
- static void
- StatusMesg (StringPtr s)
- {
- Rect r;
-
- SetRect (&r, xMid-40, yOffMesg, xMid+40, yOffMesg+20);
- TextBox (s+1, (long) s[0], &r, teJustCenter);
- StrCpy (statusStr, s);
- }
-
-
- static void
- GameOver (StringPtr mesg)
- {
- HiliteControl (restartCtl, normalHilite);
- StatusMesg (mesg);
- wait = true;
- }
-
-
-
- static void
- SelectPlayer (void)
- {
- BlobHandle b;
- short i;
-
- i = (moves + firstPlayer) % 2; /* 0 = X, 1 = O */
- HiliteBlob (GetBlobHandle (tttDonors, i), inFullBlob, normalDraw);
- HiliteBlob (GetBlobHandle (tttDonors, 1 - i), inFullBlob, dimDraw);
- if (i)
- StatusMesg ("\pO's Move");
- else
- StatusMesg ("\pX's Move");
- /*
- * Freeze board except for positions occupied by current player and
- * empty positions.
- * This allows pieces to be played either by playing the piece at
- * the top, or by duplicating them on the board. (Can't drag onto
- * another of own pieces, since replace transactions are disallowed.)
- */
- ThawBlobSet (tttReceptors);
- for (b = FirstBlob (tttReceptors); b != nil; b = NextBlob (b))
- {
- if (BGlob (b) != nil && BGlob (b) != GetBlobHandle (tttDonors, i))
- FreezeBlob (b);
- }
- }
-
-
- static void
- Restart (void)
- {
- HiliteControl (restartCtl, dimHilite);
- ZUnglueGlobSet (tttReceptors);
- HiliteBlobSet (tttReceptors, inFullBlob, normalDraw);
- moves = 0;
- SelectPlayer ();
- wait = false;
- }
-
-
- /*
- * Dim the board positions that are not part of the win. Dim them all
- * on "cat's game."
- */
-
- static void
- ShowWinner (short pos)
- {
- short i;
- BlobHandle b;
-
- for (i = 0; i < 9; ++i)
- {
- b = GetBlobHandle (tttReceptors, i);
- if ((pos % 2) == 0) /* this pos not part of win */
- HiliteBlob (b, inFullBlob, dimDraw); /* so dim it */
- pos >>= 1;
- }
- }
-
- static void
- TestConfig (short pos, short testPos)
- {
- short i;
- BlobHandle b;
-
- if ((pos & testPos) == testPos) /* have a win */
- {
- haveWin = true;
- ShowWinner (testPos);
- }
- }
-
-
- static void
- TestWin (BlobHandle b, short boardPos)
- {
- if (!haveWin) /* don't bother if other player already won */
- {
- TestConfig (boardPos, 0x007); /* top row */
- TestConfig (boardPos, 0x038); /* middle row */
- TestConfig (boardPos, 0x1c0); /* bottom row */
- TestConfig (boardPos, 0x049); /* left column */
- TestConfig (boardPos, 0x092); /* middle column */
- TestConfig (boardPos, 0x124); /* right column */
- TestConfig (boardPos, 0x111); /* diagonal */
- TestConfig (boardPos, 0x054); /* diagonal */
- if (haveWin)
- {
- if (b == xBlob)
- {
- GameOver ("\pX Wins"); /* loser goes first next time */
- firstPlayer = 1;
- }
- else
- {
- GameOver ("\pO Wins");
- firstPlayer = 0;
- }
- }
- }
- }
-
-
- static short
- BoardPos (BlobHandle b)
- {
- short i, mask, result;
- BlobHandle b2;
-
- result = 0;
- mask = 1;
- for (i = 0; i < 9; ++i)
- {
- b2 = GetBlobHandle (tttReceptors, i);
- if ((**b2).glob == b) /* board occupied by desired piece */
- result |= mask;
- mask <<= 1;
- }
- return (result);
- }
-
-
- static void
- CheckStatus (void)
- {
- short xbPos, obPos;
-
- haveWin = false;
- xbPos = BoardPos (xBlob);
- obPos = BoardPos (oBlob);
- TestWin (xBlob, xbPos);
- TestWin (oBlob, obPos);
- if (!haveWin) /* no win, but board might be full now */
- {
- if ((xbPos | obPos) == 0x1ff)
- {
- ShowWinner (0);
- GameOver ("\pCat's Game");
- firstPlayer = 1 - firstPlayer; /* alternate on a draw */
- }
- }
- }
-
-
- static pascal void
- Mouse (Point pt, long t, short mods)
- {
- short result;
- ControlHandle ctl;
-
- if (FindControl (pt, wind, &ctl))
- {
- if (TrackControl (ctl, pt, nil))
- {
- Restart ();
- }
- }
- else if (!wait)
- {
- BlobClick (pt, t, tttDonors, tttReceptors);
- result = BClickResult ();
- if (result == bcGlue || result == bcDup)
- {
- ++moves;
- CheckStatus ();
- if (!wait) /* no win yet */
- SelectPlayer ();
- }
- }
- }
-
-
- static pascal void
- Update (Boolean resized)
- {
- DrawControls (wind);
- StatusMesg (statusStr);
- DrawGrid (3, 3, xOffBoard, yOffBoard, bSqSize, bSqSize, barWidth, barWidth);
- DrawBlobSet (tttDonors);
- DrawBlobSet (tttReceptors);
- }
-
-
- static pascal void
- Activate (Boolean active)
- {
- if (active)
- {
- SetDragRects (wind);
- SetBCPermissions (false, false, true, false, false);
- }
- }
-
-
- static pascal void
- DrawRBlob (BlobHandle bDst, BlobHandle bSrc, short partCode)
- {
- Rect r;
-
- if (partCode == inStatBlob)
- {
- r = BStatBox (bDst);
- EraseRect (&r);
- }
- else
- {
- r = BDragBox (bDst);
- EraseRect (&r);
- FrameRect (&r);
- InsetRect (&r, 2, 2);
- FrameRect (&r);
- }
- }
-
-
- static pascal void
- DrawDBlob (BlobHandle bDst, BlobHandle bSrc, short partCode)
- {
- Rect r;
-
- r = BDragBox (bDst);
- EraseRect (&r);
- PenSize (2, 2);
- FrameRect (&r);
- PenSize (1, 1);
- MoveTo (r.left+pSqSize/2-4, r.bottom-pSqSize/2+5);
- DrawChar ((char) GetBRefCon (bSrc));
- }
-
-
- /*
- * Make receptor blobs
- */
-
- static void
- MakeRBlob (Rect *r)
- {
- BlobHandle b;
- Rect r2;
-
- b = NewBlob (tttReceptors, true, 0, false, 0L);
- r2 = *r;
- InsetRect (&r2, 1, 1);
- SetProcRectBlob (b, DrawRBlob, &r2, r);
- }
-
-
- static void
- MakeReceptors (void)
- {
- tttReceptors = NewBlobSet ();
- MakeBlobGrid (3, 3, xOffBoard, yOffBoard, bSqSize, bSqSize,
- barWidth, barWidth, &MakeRBlob);
- }
-
-
- /*
- * Make donor blobs
- */
-
- static void
- MakeDBlob (BlobHandle *b, short ch, short x, short y)
- {
- Rect r;
-
- *b = NewBlob (tttDonors, true, 9, false, 0L);
- SetRect (&r, 0, 0, pSqSize, pSqSize);
- OffsetRect (&r, x, y);
- SetProcRectBlob (*b, DrawDBlob, &r, &r);
- SetBRefCon (*b, ch);
- }
-
-
- static void
- MakeDonors (void)
- {
- tttDonors = NewBlobSet ();
- MakeDBlob (&xBlob, 'X', xMid-pSqSize-5, yOffPiece);
- MakeDBlob (&oBlob, 'O', xMid+5, yOffPiece);
- }
-
-
- void
- TttInit (void)
- {
- Rect r;
-
- SkelWindow (wind = GetDemoWind (tttWindRes),
- Mouse, /* mouse clicks */
- nil, /* key clicks */
- Update, /* updates */
- Activate, /* activate/deactivate events */
- nil, /* close window */
- DoWClobber, /* dispose of window */
- nil, /* idle proc */
- false); /* irrelevant, since no idle proc */
-
- MakeReceptors ();
- MakeDonors ();
- SetRect (&r, xMid-45, yOffBut, xMid+45, yOffBut+20);
- restartCtl = NewControl (wind, &r, "\pRestart", true, 0, 0, 0,
- pushButProc, 0L);
- Restart ();
- MakeFrontWind (wind);
- }
-